package cn.jtfadmin.base.filesystem.config.excel;

import cn.afterturn.easypoi.cache.manager.IFileLoader;
import cn.afterturn.easypoi.cache.manager.POICacheManager;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.jtfadmin.base.filesystem.annos.File;
import cn.jtfadmin.base.filesystem.config.FileSystem;
import cn.jtfadmin.base.lang.common.utils.ReflectionUtils;
import cn.jtfadmin.base.lang.config.ApplicationHolder;
import cn.jtfadmin.base.lang.config.excel.ExcelResultHandler;
import org.apache.poi.util.IOUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * easypoi 自定义加载文件<br/>
 * 当项目启动时设置easypoi 加载文件方法
 *
 * @author jtf
 * @see POICacheManager#setFileLoader(IFileLoader)
 * @since 0.0.1
 */
@Component
@Lazy(false)
public class ExcelFileConfig implements ApplicationListener<ContextRefreshedEvent>, ExcelResultHandler {


    private FileSystem fileSystem;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext parent = contextRefreshedEvent.getApplicationContext().getParent();
        if (Objects.isNull(parent)) {
            this.fileSystem = contextRefreshedEvent.getApplicationContext().getBean(FileSystem.class);
            POICacheManager.setFileLoader(new FileLoad());
        }
    }

    @Override
    public <T> T handle(T data) {
        Map<String, String> fieldNameDir = new HashMap<>();
        ReflectionUtils.getDeclaredFields(data.getClass()).stream()
                .forEach(t->{
                   File f =  t.getAnnotation(File.class);
                   if(f!=null){
                       fieldNameDir.put(t.getName(), f.dirName());
                   }
                });
        for (Map.Entry<String, String> fieldNameDirIndex : fieldNameDir.entrySet()) {
            Object fieldValue = ReflectionUtils.getFieldValue(data, fieldNameDirIndex.getKey());
            if(fieldValue != null){
                String s = fileSystem.copyFileAndDelSource(Paths.get(fieldValue.toString()), fieldNameDirIndex.getValue());
                ReflectionUtils.setFieldValueIfPossibly(data, fieldNameDirIndex.getKey(), s);
            }
        }
       return data;
    }

    public class FileLoad implements IFileLoader {

        @Override
        public byte[] getFile(String url) {
            InputStream fileis = null;
            try {

                //判断是否是网络地址
                if (url.startsWith("http")) {
                    URL urlObj = new URL(url);
                    URLConnection urlConnection = urlObj.openConnection();
                    urlConnection.setConnectTimeout(30 * 1000);
                    urlConnection.setReadTimeout(60 * 1000);
                    urlConnection.setDoInput(true);
                    fileis = urlConnection.getInputStream();
                } else {
                    Resource resource = ApplicationHolder.getApplicationContext().getResource(url);
                    if(resource.exists()){
                        fileis = resource.getInputStream();
                    }else {
                        fileis = fileSystem.getFileInputStream(url);
                    }

                }
                return StreamUtils.copyToByteArray(fileis);
            } catch (Exception e) {

            } finally {
                IOUtils.closeQuietly(fileis);
            }
            return null;
        }
    }
}
